#include <stdio.h>


union 
    {
        int i;      unsigned int ui;    float f;    // i、ui、f共享4字节存储空间，机器码相同，数据类型不同
        short s;    unsigned short us;    // s、us共享双字节存储空间，机器码相同，数据类型不同
        char c;     unsigned char uc;    // c、uc、f共享4字节存储空间，机器码相同，数据类型不同
    } t;

void hex_out(char a)  // 输出8位数据的16进制数
{
    const char HEX[] = "0123456789ABCDEF";
    // 求 a 的16进制的最高位和最低位
    printf("%c%c", HEX[(a & 0xF0) >> 4], HEX[a & 0x0F]);
}

void out_1byte(char *addr)  // 用十六进制输出地址中的8位数据机器码
{
    hex_out(*(addr + 0));
}

void out_2byte(char *addr)  // 用十六进制输出地址中的16位数据机器码
{
    // 小端模式优先输出高字节
    hex_out(*(addr + 1));
    hex_out(*(addr + 0));
}

void out_4byte(char *addr)  // 用十六进制输出地址中的32位数据机器码
{
    // 小端模式优先输出高字节
    hex_out(*(addr + 3));   // C7
    hex_out(*(addr + 2));   // 7F
    hex_out(*(addr + 1));   // FF
    hex_out(*(addr + 0));   // FF
}

void main()
{
    /* 
        addr         FF
        addr + 1     FF
        addr + 2     7F
        addr + 3     C7

        1、&a是int型变量a的地址
        2、(char *)将int型指针（指向4个字节）转换成char型指针（指向一个字节）
        3、char *p声明一个char型指针变量，接受转换的地址。
    */
    
    t.i = 0xC77FFFFF;   // 通过机器码赋值，联合体中所有变量共享该机器码
    out_4byte((char *)&t.i);    // 输出 i 的机器码和真值，& 表示引用变量地址
    printf(" = %d \n", t.i);    // C77FFFFF = -947912705 

    out_4byte((char *)&t.ui);    // 输出 ui 的机器码和真值
    printf(" = %u \n", t.ui);    // C77FFFFF = 3347054591

    out_4byte((char *)&t.f);    // 输出 f 的机器码和真值
    printf(" = %f \n", t.f);    // C77FFFFF = -65535.996094  
    
    out_2byte((char *)&t.s);    // 输出 s 的机器码和真值
    printf(" = %d \n", t.s);    // FFFF = -1 

    out_2byte((char *)&t.us);    // 输出 us 的机器码和真值
    printf(" = %u \n", t.us);    // FFFF = 65535

    out_1byte((char *)&t.c);    // 输出 c 的机器码和真值
    printf(" = %d \n", t.c);    // FF = -1

    out_1byte((char *)&t.uc);    // 输出 uc 的机器码和真值
    printf(" = %d \n", t.uc);    // FF = 255 
    
    
}